home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 21 / CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso / CUCD / Magazine / C_Tutorial / Part-9 / wb0 / idcmp.c < prev    next >
C/C++ Source or Header  |  1998-01-03  |  9KB  |  359 lines

  1. #include "idcmp.h"
  2. #include "drawwin.h"
  3. #include "gadgets.h"
  4. #include "loadsave.h"
  5. #include "menu.h"
  6. #include "toolwin.h"
  7. #include "arexx.h"
  8.  
  9. #include<dos/rdargs.h>
  10.  
  11. #include<string.h>
  12. #include<stdio.h>
  13.  
  14. #include<clib/dos_protos.h>
  15. #include<clib/exec_protos.h>
  16. #include<clib/gadtools_protos.h>
  17. #include<clib/graphics_protos.h>
  18. #include<clib/intuition_protos.h>
  19.  
  20. static void doGadgetUp(struct Window*, UWORD, struct Gadget*);
  21. static int  doMenuPick(struct Window*, UWORD);
  22. static int  doARexx(struct RexxMsg*, struct Window*);
  23.  
  24. static void new(struct Window*);
  25.  
  26. static int  isCommand(char*, char*, char*, LONG*);
  27. static void freeCommand(void);
  28.  
  29. /* Our message handling code */
  30. void handleIDCMP()
  31. {
  32.     char* text = "Hello World!";
  33.     int going = TRUE;
  34.     int drawing = FALSE;
  35.     ULONG drawsig, toolsig, arexxsig, gotsig;
  36.     struct Window* drawwin = getDrawWin();
  37.     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  38.     arexxsig = getARexxSig();
  39.     while(going)
  40.     {
  41.         struct IntuiMessage* intuimsg;
  42.         /* Only include tool window signal mask if window is open */
  43.         toolsig = getToolSig();
  44.         /* Wait for messages to arrive */
  45.         gotsig = Wait(drawsig | toolsig | arexxsig);
  46.         /* Messages have arrived: loop through all of them */
  47.         /* Check messages from the drawing window first */
  48.         if(gotsig & drawsig)
  49.         {
  50.             while(intuimsg = GT_GetIMsg(drawwin->UserPort))
  51.             {
  52.                 /* Copy the important bits of the message */
  53.                 ULONG class = intuimsg->Class;
  54.                 UWORD code = intuimsg->Code;
  55.                 WORD mousex = intuimsg->MouseX;
  56.                 WORD mousey = intuimsg->MouseY;
  57.                 /* Reply when finished copying bits from message */
  58.                 GT_ReplyIMsg(intuimsg);
  59.                 /* Act on this message... */
  60.                 switch(class)
  61.                 {
  62.                 case IDCMP_MOUSEBUTTONS:
  63.                     switch(code)
  64.                     {
  65.                     case SELECTDOWN:
  66.                         drawing = TRUE;
  67.                         break;
  68.                     case SELECTUP:
  69.                         drawing = FALSE;
  70.                         break;
  71.                     }
  72.                     /* break; omitted so we draw on click, too */
  73.                 case IDCMP_MOUSEMOVE:
  74.                     if(drawing)
  75.                     {
  76.                         Move(drawwin->RPort, mousex, mousey);
  77.                         Text(drawwin->RPort, text, strlen(text));
  78.                     }
  79.                     break;
  80.                 case IDCMP_MENUPICK:
  81.                     going = doMenuPick(drawwin, code);
  82.                     drawwin = getDrawWin();
  83.                     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  84.                     break;
  85.                 }
  86.             }
  87.         }
  88.         /* Now check messages from the tool window */
  89.         if(going && (gotsig & toolsig))
  90.         {
  91.             struct Window* toolwin = getToolWin();
  92.             while(toolwin && (intuimsg = GT_GetIMsg(toolwin->UserPort)))
  93.             {
  94.                 /* Copy the important bits of the message */
  95.                 ULONG class = intuimsg->Class;
  96.                 UWORD code = intuimsg->Code;
  97.                 APTR iaddr = intuimsg->IAddress;
  98.                 /* Reply when finished copying bits from message */
  99.                 GT_ReplyIMsg(intuimsg);
  100.                 /* Act on this message... */
  101.                 switch(class)
  102.                 {
  103.                 case IDCMP_CLOSEWINDOW:
  104.                     closeToolWin();
  105.                     /* Update our local toolwin, so we stop loop */
  106.                     toolwin = NULL;
  107.                     uncheckToolBar(drawwin);
  108.                     break;
  109.                 case IDCMP_REFRESHWINDOW:
  110.                     /* You *MUST* remember to ask for and handle these refresh messages */
  111.                     GT_BeginRefresh(toolwin);
  112.                     GT_EndRefresh(toolwin, TRUE);
  113.                     break;
  114.                 case IDCMP_GADGETUP:
  115.                     doGadgetUp(drawwin, code, (struct Gadget*)iaddr);
  116.                     break;
  117.                 case IDCMP_MENUPICK:
  118.                     going = doMenuPick(drawwin, code);
  119.                     /* Update our local toolwin, so we stop loop */
  120.                     toolwin = getToolWin();
  121.                     drawwin = getDrawWin();
  122.                     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  123.                     break;
  124.                 }
  125.             }
  126.         }
  127.         /* Now check messages from the ARexx port */
  128.         if(going && (gotsig & arexxsig))
  129.         {
  130.             struct RexxMsg* msg;
  131.             while(going && (msg = getARexxMsg()))
  132.                 going = doARexx(msg, drawwin);
  133.         }
  134.     }
  135. }
  136.  
  137. /* Process IDCMP_GADGETUP event */
  138. static void doGadgetUp(struct Window* drawwin, UWORD code, struct Gadget* gad)
  139. {
  140.     switch(gad->GadgetID)
  141.     {
  142.     case MYBUT_ID:
  143.         /* Our button was clicked!  Set foreground to next pen colour */
  144.         nextFgPen(drawwin);
  145.         break;
  146.     case MYPAL_ID:
  147.         /* Our palette gadget was clicked!  Set foreground to gadget colour */
  148.         setFgPen(drawwin, code);
  149.         break;
  150.     }
  151. }
  152.  
  153. /* Process IDCMP_MENUPICK event */
  154. static int doMenuPick(struct Window* drawwin, UWORD code)
  155. {
  156.     UWORD menuCode, menuNumber, itemNumber;
  157.     /* Loop over all the menu selections in the menu code */
  158.     struct MenuItem* item;
  159.     for(menuCode = code;
  160.             menuCode != MENUNULL;
  161.             menuCode = item->NextSelect)
  162.     {
  163.         item = ItemAddress(drawwin->MenuStrip, menuCode);
  164.         /* Extract the menu number and menu item number from the menu code */
  165.         menuNumber = MENUNUM(menuCode);
  166.         itemNumber = ITEMNUM(menuCode);
  167.         /* Now decide what to do based on what menu item was selected */
  168.         switch(menuNumber)
  169.         {
  170.         case 0:  /* Project menu */
  171.             switch(itemNumber)
  172.             {
  173.             case 0:  /* Load */
  174.                 return load();
  175.             case 1:  /* Save */
  176.                 save();
  177.                 break;
  178.             case 3:  /* New (item 2 is the bar!) */
  179.                 new(drawwin);
  180.                 break;
  181.             case 5:  /* Quit (item 4 is the bar!) */
  182.                 return FALSE;
  183.             }
  184.             break;
  185.         case 1:  /* Pen menu */
  186.             switch(itemNumber)
  187.             {
  188.             case 0:  /* Next */
  189.                 nextFgPen(drawwin);
  190.                 break;
  191.             case 1:  /* Prev */
  192.                 prevFgPen(drawwin);
  193.                 break;
  194.             case 3:  /* Reset (item 2 is the bar!) */
  195.                 resetFgPen(drawwin);
  196.                 break;
  197.             }
  198.             break;
  199.         case 2:  /* Tools menu */
  200.             switch(itemNumber)
  201.             {
  202.             case 0:  /* Screen Bar */
  203.                 ShowTitle(drawwin->WScreen, item->Flags & CHECKED);
  204.                 break;
  205.             case 1:  /* Tool Bar */
  206.                 /* Do the open or close */
  207.                 if(item->Flags & CHECKED)
  208.                 {
  209.                     /* If the open fails, stop immediately */
  210.                     if(!openToolWin())
  211.                         return FALSE;
  212.                 }
  213.                 else
  214.                     closeToolWin();
  215.                 break;
  216.             }
  217.         }
  218.     }
  219.     /* Keep going */
  220.     return TRUE;
  221. }
  222.  
  223. static void new(struct Window* win)
  224. {
  225.     SetRast(win->RPort, 0);
  226. }
  227.  
  228. /* Our RDArgs structure for use with ReadArgs() */
  229. static struct RDArgs* myrdargs = NULL;
  230.  
  231. int createArgs()
  232. {
  233.     if(myrdargs = AllocDosObject(DOS_RDARGS, NULL))
  234.     {
  235.         /* Disable prompting on stdin when "?" is the argument */
  236.         myrdargs->RDA_Flags = RDAF_NOPROMPT;
  237.         return TRUE;
  238.     }
  239.     else
  240.         printf("Error: could not allocate args for ARexx commands\n");
  241.     return FALSE;
  242. }
  243.  
  244. void freeArgs()
  245. {
  246.     if(myrdargs)
  247.         FreeDosObject(DOS_RDARGS, myrdargs);
  248. }
  249.  
  250. /* The result of a ReadArgs() while parsing commands */
  251. static struct RDArgs* rdargs = NULL;
  252.  
  253. /* Test if a string matches a command, using ReadArgs() */
  254. static int isCommand(char* text, char* comm,
  255.                                          char* templ, LONG* args)
  256. {
  257.     int clen = strlen(comm);
  258.     if(strnicmp(text, comm, clen) == 0)
  259.     {
  260.         /* Is the command followed by some whitespace? */
  261.         if(text[clen] == ' ' || text[clen] == '\t')
  262.         {
  263.             int tlen = strlen(text);
  264.             /* Set up our myrdargs so we can use ReadArgs() */
  265.             myrdargs->RDA_Source.CS_Buffer = text+clen+1;
  266.             myrdargs->RDA_Source.CS_Length = tlen-clen;
  267.             myrdargs->RDA_Source.CS_CurChr = 0;
  268.             myrdargs->RDA_DAList = NULL;
  269.             myrdargs->RDA_Buffer = NULL;
  270.             /* Temporarily end the string with a return... */
  271.             /* (Needed to get ReadArgs() to work properly) */
  272.             text[tlen] = '\n';
  273.             rdargs = ReadArgs(templ, args, myrdargs);
  274.             /* ... now we must reinstate the string's terminator */
  275.             text[tlen] = '\0';
  276.             return rdargs != NULL;
  277.         }
  278.     }
  279.     return NULL;
  280. }
  281.  
  282. static void freeCommand()
  283. {
  284.     if(rdargs)
  285.     {
  286.         FreeArgs(rdargs);
  287.         rdargs = NULL;
  288.     }
  289. }
  290.  
  291. /* The maximum number of arguments for our commands */
  292. #define MAX_ARGS (3)
  293.  
  294. #define COMM_QUIT        "QUIT"
  295.  
  296. #define COMM_NEW        "NEW"
  297.  
  298. #define COMM_PEN        "PEN"
  299. #define TEMPL_PEN        "PEN/N"
  300. enum PEN_ARGS { PEN_PEN };
  301.  
  302. #define COMM_DRAW        "DRAW"
  303. #define TEMPL_DRAW    "X/N,Y/N,TEXT/F"
  304. enum DRAW_ARGS { DRAW_X, DRAW_Y, DRAW_TEXT };
  305.  
  306. /* Process an ARexx message */
  307. static int doARexx(struct RexxMsg* msg, struct Window* drawwin)
  308. {
  309.     int going = TRUE;
  310.     /* By default, our reply will indicate an error */
  311.     LONG rc = 20;
  312.     char* res = NULL;
  313.     char* command = msg->rm_Args[0];
  314.     /* Parse the command */
  315.     if(stricmp(command, COMM_QUIT) == 0)
  316.     {
  317.         going = FALSE;
  318.         /* We recognised the command, so set rc to zero */
  319.         rc = 0;
  320.         res = "Hello Painter is quitting";
  321.     }
  322.     else if(stricmp(command, COMM_NEW) == 0)
  323.     {
  324.         new(drawwin);
  325.         rc = 0;
  326.         res = "Display cleared";
  327.     }
  328.     else
  329.     {
  330.         LONG args[MAX_ARGS];
  331.         int i;
  332.         for(i=0; i<MAX_ARGS; i++)
  333.             args[i] = NULL;
  334.         if(isCommand(command, COMM_PEN, TEMPL_PEN, args))
  335.          {
  336.             /* args[0] holds the pen number to use */
  337.             LONG* nptr = (LONG*)(args[PEN_PEN]);
  338.             setFgPen(drawwin, *nptr);
  339.             rc = 0;
  340.             res = "Pen set";
  341.         }
  342.         else if(isCommand(command, COMM_DRAW, TEMPL_DRAW, args))
  343.          {
  344.             /* args[DRAW_X] and args[DRAW_Y] hold the coordinate */
  345.             /* args[DRAW_TEXT] holds the text to be drawn */
  346.             LONG* xptr = (LONG*)(args[DRAW_X]);
  347.             LONG* yptr = (LONG*)(args[DRAW_Y]);
  348.             char* text = (char*)(args[DRAW_TEXT]);
  349.             Move(drawwin->RPort, *xptr, *yptr);
  350.             Text(drawwin->RPort, text, strlen(text));
  351.             rc = 0;
  352.             res = "Text drawn";
  353.         }
  354.         freeCommand();
  355.     }
  356.     replyARexxMsg(msg, rc, res);
  357.     return going;
  358. }
  359.